package redis

import (
	"backend/config"
	"context"
	"fmt"
	"time"

	gredis "github.com/go-redis/redis/v8"
)

var rdbToken *gredis.Client

func InitClient(rCfg *config.RedisConfig) (err error) {
	rdbToken = gredis.NewClient(&gredis.Options{
		Addr:     fmt.Sprintf("%s:%d", rCfg.Host, rCfg.Port),
		Password: rCfg.Password, // no password set
		DB:       rCfg.DB,       // use default DB
		PoolSize: rCfg.PoolSize, // 连接池大小
	})

	ctxToken, cancelToken := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancelToken()

	_, err = rdbToken.Ping(ctxToken).Result()
	if err != nil {
		return err
	}
	return nil
}

func GetTokenRdb() *gredis.Client {
	return rdbToken
}

func Query(rdb *gredis.Client, key string) (string, error) {
	ctx := context.Background()
	val, err := rdb.Get(ctx, key).Result()
	return val, err
}

func SetKey(rdb *gredis.Client, key, value string) error {
	ctx := context.Background()
	err := rdb.Set(ctx, key, value, 0).Err()
	return err
}

func SetKeyWithExp(rdb *gredis.Client, key, value string, exp time.Duration) error {
	ctx := context.Background()
	err := rdb.Set(ctx, key, value, exp).Err()
	return err
}

func DelKey(rdb *gredis.Client, key string) error {
	ctx := context.Background()
	err := rdb.Del(ctx, key).Err()
	return err
}

func QueryHashTable(rdb *gredis.Client, hKey, hField string) (string, error) {
	ctx := context.Background()
	val, err := rdb.HGet(ctx, hKey, hField).Result()
	return val, err
}

func QueryHashTableAll(rdb *gredis.Client, hKey string) (map[string]string, error) {
	ctx := context.Background()
	vals, err := rdb.HGetAll(ctx, hKey).Result()
	return vals, err
}

func SetHashTable(rdb *gredis.Client, hKey, hField, value string) error {
	ctx := context.Background()
	err := rdb.HSet(ctx, hKey, hField, value).Err()
	return err
}

func LPushMQ(rdb *gredis.Client, mKey, value string) error {
	ctx := context.Background()
	err := rdb.LPush(ctx, mKey, value).Err()
	return err
}

func RPopMQ(rdb *gredis.Client, mKey string) (string, error) {
	ctx := context.Background()
	value, err := rdb.RPop(ctx, mKey).Result()
	return value, err
}

func Zadd(rdb *gredis.Client, zkey string, smmap map[string]float64) (int64, error) {
	ctx := context.Background()
	scoreMembers := []*gredis.Z{}
	for members, score := range smmap {
		scoreMembers = append(scoreMembers, &gredis.Z{
			Score:  score,
			Member: members,
		})
	}
	return rdb.ZAdd(ctx, zkey, scoreMembers...).Result()
}

func Zrevrange(rdb *gredis.Client, zkey string, start, stop int64) ([]string, error) {
	ctx := context.Background()
	return rdb.ZRevRange(ctx, zkey, start, stop).Result()
}

func Zcount(rdb *gredis.Client, zkey string) (int64, error) {
	ctx := context.Background()
	return rdb.ZCount(ctx, zkey, "0", "+inf").Result()
}

func Zscore(rdb *gredis.Client, zkey, zmember string) (float64, error) {
	ctx := context.Background()
	return rdb.ZScore(ctx, zkey, zmember).Result()
}
